package com.webrtc.demo

import com.webrtc.demo.call.GroupNegotiate
import com.webrtc.demo.call.MediaType
import com.webrtc.demo.call.OnSignalEventListener
import com.webrtc.demo.call.RTCSignalClient
import com.webrtc.demo.util.Utils
import com.webrtc.demo.util.logD
import org.webrtc.IceCandidate
import org.webrtc.SessionDescription

class MultiChatHelper(
    val localUid: String,
    private val remoteUids: List<String>,
    roomId: String?,
    callerUid: String?,
    private val listener: MutiChatUserListener
) {
    val conversationId: String
    val isCaller: Boolean

    private var ackIndex = 0
    val otherConnections: MutableMap<String, Connection> = mutableMapOf()
    private val peers: MutableList<String> = mutableListOf() // 已加入会话的用户（除我以外）
    private val childGroupingManagers: MutableList<String> = mutableListOf() // 当前用户管理的微中心

    // 接收到广播或者收到ack，执行本地添加
    private fun addUser(uid: String, sendOffer: Boolean) {
        if (!peers.contains(uid)) {
            peers.add(uid)
            log("新加入用户 $uid")

            otherConnections[uid] = ConnectionManager.get(uid)
                .also { it.cId = conversationId }
            otherConnections[uid]!!.textStation.registerListener {
                listener.onDataReceived(uid, it)
                log("收到来自$uid" + "的消息：$it" + " 进行转发...")
                send(it, uid)
            }
        }

        if (sendOffer) {
            otherConnections[uid]?.connect()
        }
    }

    fun send(data: String, excludeUid: String? = null) {
        var transpond = false
        otherConnections.values.forEach {
            if (it.uid != excludeUid) {
                if (excludeUid != null) {
                    transpond = true
                    log("转发给" + it.uid + "：$data")
                }
                it.textStation.send(data)
            }
        }
        if (!transpond && excludeUid != null) {
            log("无需转发！")
        }
    }

    interface MutiChatUserListener {
        // 是发起者再处理此消息
        fun onUserDeny(uid: String)

        fun onDataReceived(uid: String, data: String)
    }

    private fun uidsAppend(uids: List<String>, vararg removes: String): String {
        val sb = StringBuilder()
        uids.forEach {
            if (!removes.contains(it))
                sb.append(it).append(',')
        }
        return sb.toString()
    }

    private fun log(msg: String) = logD(TAG, "conversationId:${this.conversationId}，$msg")

    companion object {
        const val TAG = "MultiChatHelper"

        private const val GROUPING_COUNT = 3
    }

    private val signalEventListener: OnSignalEventListener

    init {
        this.conversationId = roomId ?: genCId()
        this.isCaller = roomId == null

        signalEventListener = object : OnSignalEventListener {
            override fun onGroupNegotiate(
                uid: String,
                roomid: String,
                type: GroupNegotiate
            ): Boolean {
                return if (roomid == this@MultiChatHelper.conversationId) {

                    when (type) {
                        GroupNegotiate.GROUP_CALL -> {
                            return false
                        }
                        GroupNegotiate.GROUP_ACK -> { // 能收到ack说明我是发起者
                            log("$uid 返回了Ack")
                            ackIndex++

                            val groupingManager = ackIndex % GROUPING_COUNT == 0 // 微中心管理者
                            if (ackIndex < GROUPING_COUNT/*发起者微中心下的用户*/ || groupingManager) {
                                // 本地添加该用户
                                addUser(uid, sendOffer = true)

                                if (groupingManager) {
                                    childGroupingManagers.add(uid)
                                }
                            }

                            // 广播给发起者微中心以为的微中心
                            if (childGroupingManagers.isNotEmpty() && !groupingManager) {
                                val filterList =
                                    mutableListOf(childGroupingManagers.last()).filter { it != uid }
                                if (filterList.isNotEmpty()) {
                                    RTCSignalClient.sendJoinGroupBroadcast(
                                        filterList,
                                        this@MultiChatHelper.conversationId,
                                        uid
                                    ) {
                                        log("新人" + uid + "加入(ack)广播成功，广播给："
                                                + filterList.joinToString(separator = ",") { it })
                                    }
                                }
                            }
                        }
                        GroupNegotiate.GROUP_DENY -> {
                            // 收到拒绝消息，说明我是发起人，可能要移除该用户
                            listener.onUserDeny(uid)
                        }
                    }

                    true
                } else false
            }

            override fun onGroupJoinBroadcast(uid: String, newid: String, roomid: String): Boolean {
                return if (roomid == conversationId) {
                    log("收到新人" + newid + "加入广播，来自$uid")
                    addUser(newid, true)
                    true
                } else false
            }

            override fun onOffer(
                uid: String,
                sdp: String,
                mediaType: MediaType,
                roomid: String?
            ): Boolean {
                // 接收之前的人
                return if (roomid == conversationId) {
                    // 被动接收的offer，针对我加入时，之前的人会主动加我
                    if (!otherConnections.containsKey(uid))
                        addUser(uid, sendOffer = false)

                    otherConnections[uid]?.onOffer(
                        SessionDescription(
                            SessionDescription.Type.OFFER,
                            sdp
                        )
                    )

                    log("收到 $uid 的offer")

                    true
                } else false
            }

            override fun onAnswer(
                uid: String, sdp: String,
                mediaType: MediaType, roomid: String?
            ): Boolean {
                return if (roomid == conversationId) {
                    otherConnections[uid]?.let {
                        it.onAnswer(SessionDescription(SessionDescription.Type.ANSWER, sdp))

                        log("收到$uid 的answer")

                        true
                    } ?: false
                } else false
            }

            override fun onCandidate(
                uid: String, ice: IceCandidate,
                mediaType: MediaType, roomid: String?
            ): Boolean {
                return if (roomid == conversationId) {
                    otherConnections[uid]?.let {
                        it.onIceCandidate(ice, true)
                        true
                    } ?: false
                } else false
            }
        }
        // 处理连接请求
        RTCSignalClient.addOnSignalEventListener(signalEventListener)

        // 启动
        if (isCaller) {
            RTCSignalClient.sendGroupNegotiate(
                uidsAppend(remoteUids),
                this.conversationId,
                GroupNegotiate.GROUP_CALL
            ) {
                log("发送多人群聊Call信号成功")
            }
        } else {// 响应
            RTCSignalClient.sendGroupNegotiate(
                callerUid!!,
                this.conversationId,
                GroupNegotiate.GROUP_ACK
            ) {
                log("发送 多人群聊ACK 信号成功")
            }
        }
    }

    private fun genCId(): String { // 我的id+当前毫秒时间+其余用户id 对此字符串计算md5
        val sb = StringBuilder(localUid)
        sb.append(System.currentTimeMillis())
        remoteUids.forEach { sb.append(it) }
        return Utils.md5Decode32(sb.toString())!!
    }

    fun close() {
        RTCSignalClient.removeOnSignalEventListener(signalEventListener)

        otherConnections.values.forEach {
            it.close()
        }
    }
}